import jwt
import redis
from rest_framework.response import Response

from OA_pro import settings
from primary.models import UserModel, RoleAccessModel, AccessModel


def check_login(func):
    def wrapper(self, request, *args, **kwargs):
        # 设置白名单路由(除登录注册等基本页面以外，尽量放token验证后面)
        if request.path == '/primary/login/' or request.path == '/primary/smscode/':
            return func(self, request, *args, **kwargs)

        # token验证
        token = request.headers.get('token')
        # 判断token是否已经被禁用
        rds = redis.Redis(host='127.0.0.1', port=6379)
        is_exists = rds.exists('token_%s' % token)  # exists判断键是否存在
        if is_exists:  # redis中有这个token 代表此token已禁用
            return Response({
                'code': 403, 'msg': '此token不可使用'
            })
        try:
            payload = jwt.decode(token, key=settings.SECRET_KEY, algorithms='HS256')
        except:
            return Response({
                'code': 403, 'msg': '用户未登录'
            })

        # 路由访问权限验证
        request.user_id = payload.get('user_id')
        request.user = UserModel.objects.filter(id=request.user_id).first()
        # 创建该用户在（角色-权限 多对多表）的查询结果集
        role_access_list = RoleAccessModel.objects.filter(role_id=request.user.role_id).all()
        # (如果该角色没有配置任何路由，role_access_list会为空)
        if not role_access_list:
            return Response({
                'code': 401, 'msg': '您没有访问权限！'
            })
        # 设置一个管理员权限（访问所有）
        if role_access_list[0].acc_id == 1:
            return func(self, request, *args, **kwargs)
        acc_info_list = []

        for role_access in role_access_list:
            acc_id = role_access.acc_id
            acc_info = AccessModel.objects.filter(id=acc_id).first()
            # 添加该用户所有权限对象
            acc_info_list.append(acc_info)
        global flag
        flag = False
        # 获取当前路由
        path = request.path
        # 获取当前请求方式
        method = request.method
        for access in acc_info_list:
            if access.access_path.upper() == path.upper() and access.access_method.upper() == method.upper():
                flag = True
        if not flag:
            return Response({
                'code': 401,
                'message': "您没有访问权限！"
            })

        return func(self, request, *args, **kwargs)

    return wrapper
